
#ifndef _BSSOCKET_H_
#define _BSSOCKET_H_


#include "Common.h"
#include "Network/BaseSocket.h"
#include "WorldPacket.h"
#include "Resource.h"
#include "Users.h"
#include "Character.h"
#include "Threading/AtomicCounter.h"
#include "AtomicWrappers.h"

#include <boost/thread/mutex.hpp>
#include <boost/thread/locks.hpp>

#ifndef _SOCKET_DEFINE_
#define _SOCKET_DEFINE_

#define WGS_SOCKET_WRITE_MUTEX_NAME socket_write_mutex
#define WGS_SOCKET_READ_MUTEX_NAME socket_read_mutex

#define WGS_SOCKET_WRITE_MUTEX mutable boost::mutex WGS_SOCKET_WRITE_MUTEX_NAME;
#define WGS_SOCKET_READ_MUTEX mutable boost::mutex WGS_SOCKET_READ_MUTEX_NAME;

#define WGS_SOCKET_WRITE_LOCK         boost::lock_guard<boost::mutex>  wgsSocketMutexLock(WGS_SOCKET_WRITE_MUTEX_NAME);
#define WGS_SOCKET_READ_LOCK         boost::lock_guard<boost::mutex>  wgsSocketMutexLock(WGS_SOCKET_READ_MUTEX_NAME);

#define WGS_SOCKET_LOCK_MUTEX(name) boost::lock_guard<boost::mutex>  wgsSocketMutexLock(name);

#define WGS_WEBSOCKET_WRITE_MUTEX_NAME websocket_write_mutex
#define WGS_WEBSOCKET_READ_MUTEX_NAME websocket_read_mutex

#define WGS_WEBSOCKET_WRITE_MUTEX mutable boost::mutex WGS_WEBSOCKET_WRITE_MUTEX_NAME;
#define WGS_WEBSOCKET_READ_MUTEX mutable boost::mutex WGS_WEBSOCKET_READ_MUTEX_NAME;

#define WGS_WEBSOCKET_WRITE_LOCK         boost::lock_guard<boost::mutex>  wgsWebSocketMutexLock(WGS_WEBSOCKET_WRITE_MUTEX_NAME);
#define WGS_WEBSOCKET_READ_LOCK         boost::lock_guard<boost::mutex>  wgsWebSocketMutexLock(WGS_WEBSOCKET_READ_MUTEX_NAME);


#endif


class SERVER_DECL  cBSSocket : public BaseSocket,public Resource
{
	void DeleteSocket();
protected:
       	void prepareImpl(void);
        /** Destroys data cached by prepareImpl.
         */
        void unprepareImpl(void);
        /// @copydoc Resource::loadImpl
        bool loadImpl(void);
        /// @copydoc Resource::postLoadImpl
        void postLoadImpl(void);

	void preUnloadImpl(void);
        /// @copydoc Resource::unloadImpl
        void unloadImpl(void);
        /// @copydoc Resource::calculateSize
        size_t calculateSize(void) const;

public:
	WGS_SOCKET_WRITE_MUTEX
	WGS_SOCKET_READ_MUTEX
	//WGS_SOCKET_WRITE_STATUS_MUTEX
	//WGS_SOCKET_READ_STATUS_MUTEX
  
	cBSSocket(ResourceManager* creator, const String& name, ResourceHandle handle,
            const String& group, bool isManual = false, ManualResourceLoader* loader = 0);
        ~cBSSocket();

	enum SOCKET_STATUS
	{
		SOCKET_STATUS_NONE = 0,
		SOCKET_STATUS_CONNECT = 1,
		SOCKET_STATUS_CONNECTED = 3,
		SOCKET_STATUS_ERROR = 4,
		SOCKET_STATUS_DISCONNECTING = 5,
		SOCKET_STATUS_DISCONNECT = 6
	};

	enum SOCKET_TYPE
	{
		SOCKET_TYPE_NONE	= 0,
		SOCKET_TYPE_CLIENT	= 1,
		SOCKET_TYPE_LISTEN	= 2
	};
        void OnRecvData();
        void OnSendData() {}

        void OnConnect();
        bool OnConnecting();
        void OnDisconnect();
	void OnListen();
	//void OnAccept(int fd, void * pointer);

	bool Write(const void * data, size_t bytes);
	void Accept(void);
	void Finalize(void);
	void Close(void);

	bool Listen(const char * ListenAddress, uint32 Port);

	void InitSocket(int fd, size_t readbuffersize, size_t writebuffersize, const sockaddr_in * peer);

	//继承从BaseSokcet
	bool Writable(void);
	bool WritableNotLock(void);
	bool OnRead(size_t len);
	bool OnWrite(size_t len);
	bool OnError(int errcode);
	bool OnAccept(int fd,void * pointer);
	void Disconnect();
	

	void Pong(uint32 serial);
	void TimeQuest(void);
	void TgwAck(void);

	//发送Flash 安全策略文件
	void SendFlashPolicyFile(void);

	ResourceProxy  	 m_User;	//用户验证帐号
	ResourceProxy    m_Char;    //用户当前武将（君主)
	ResourceProxy		m_channel;   //用户连接的频道


	WGSERVER_INLINE	 const SOCKET_TYPE  &  GetSocketType(void)	{	return m_socket_type; }
	WGSERVER_INLINE  void  SetSocketType(const SOCKET_TYPE & type)	{	m_socket_type = type ;	}

	WGSERVER_INLINE bool 	isServerSocket(void)	{	return m_socket_type == SOCKET_TYPE_LISTEN;	}

	WGSERVER_INLINE const uint32 & getLastTimer(void)	{	return m_last_timer;	}
	WGSERVER_INLINE void setLastTimer(const uint32 & tm)	{	m_last_timer = tm;	}



	WGSERVER_INLINE const bool & isBusy(void)	{	return m_isThreadQueued;	}
	WGSERVER_INLINE void setBusy()		{	m_isThreadQueued = true;	}
	WGSERVER_INLINE void setIdle(void)	{	m_isThreadQueued = false;	}

	bool isPacketAvailed(void);
	void setPacketAvailed(bool set);

	
	void	setCurrentCharacter(CharPtr & curChar);
	void	removeCurrentCharacter(void);
	CharPtr getCurrentCharacter(void)	{	return m_Char.getResourcePtr();	}

	void	setCurrentUser(UserPtr & user);
	void	removeCurrentUser(void);
	UserPtr	getCurrentUser(void)		{	return m_User.getResourcePtr();	}


	bool	isAuthentication(void);



	bool _OutPacket(uint16 opcode, size_t len, const void* data);
	void OutPacket(uint16 opcode, size_t len, const void* data);
	void OutPacket(size_t len,const void * data);
	void SendPacket(WorldPacket* packet);
	
	/** Get IP in numerical form
         */
        const char * GetIP() { return inet_ntoa(m_addr.sin_addr); }
        unsigned int  GetNumIP() { return (unsigned int) m_addr.sin_addr.s_addr; }
        int  GetPort()  { return (int)htons(m_addr.sin_port); }

	WGSERVER_INLINE void IncSendLock() {  ++m_writeLock; }
	WGSERVER_INLINE void DecSendLock() {  --m_writeLock; }
	WGSERVER_INLINE bool HasSendLock() { return (m_writeLock.GetVal() != 0); }
	WGSERVER_INLINE void ZeroSendLock()	{	m_writeLock.SetVal(0);	}
	WGSERVER_INLINE bool AcquireSendLock()
	{
		if(m_writeLock.SetVal(1) != 0)
			return false;
		else
			return true;
	}

	const uint32 & getRunTimer(void)                {       return m_run_timer;     }
        void    setRunTimer(const uint32 & set)         {       m_run_timer = set;      }

        //检查是否运行命令
        const bool checkRunTimerBlock(const uint32 & p_time)    {       return ((uint32)(p_time - m_last_timer)) < m_run_timer?true:false;  }

	const size_t & getSendSize()		{	return m_sendedSize;	}
	const size_t & getRealSendSize()	{	return m_compressSize;	}
	const size_t & getReadSize()		{	return m_readSize;	}

	bool	isConnected()		{	return m_socket_status.get() == SOCKET_STATUS_CONNECTED;	}

protected:

	void	initialize(void);

	uint32	  m_last_timer;
	//命令执行的最小间隔时间(默认200ms) 每秒最多5条指令
        uint32    m_run_timer;

	AtomicScalar<SOCKET_STATUS>  m_socket_status;
	SOCKET_TYPE		m_socket_type;
	
	Threading::AtomicCounter m_writeLock;

	bool		m_packetAvailed;
	bool		m_isThreadQueued;

	sockaddr_in 	m_addr;
	bool		m_deleted;	

	//发送总数据    
        size_t          m_sendedSize;
        //压缩后数据
        size_t          m_compressSize;

	//接收总数据
	size_t		m_readSize;

};

  /** Specialisation of SharedPtr to allow SharedPtr to be assigned to ArmyPtr 
    @note Has to be a subclass since we need operator=.
    We could templatise this instead of repeating per Resource subclass, 
    except to do so requires a form VC6 does not support i.e.
    ResourceSubclassPtr<T> : public SharedPtr<T>
    */
    class SERVER_DECL BSSocketPtr : public SharedPtr<cBSSocket>
    {
    public:
        BSSocketPtr() : SharedPtr<cBSSocket>() {}
        explicit BSSocketPtr(cBSSocket* rep) : SharedPtr<cBSSocket>(rep) {}
        BSSocketPtr(const BSSocketPtr& r) : SharedPtr<cBSSocket>(r) {}
        BSSocketPtr(const ResourcePtr& r);
        /// Operator used to convert a ResourcePtr to a MeshPtr
        BSSocketPtr& operator=(const ResourcePtr& r);
    protected:
        /// Override destroy since we need to delete Mesh after fully defined
        void destroy(void);
    };
	




#endif
